#pragma once

#include <memory>
#include <vector>
#include <functional>
#include "hidbox/hid_device_identifier.h"
#include "hidbox/hid_gadget_descriptor.h"
#include "hidbox/usb_gadget.h"
#include "hidbox/input_hid_device.h"
#include "hidbox/output_hid_device.h"

namespace hidbox {

/**
 * @brief HID 设备配置选项
 */
struct HIDDeviceConfig {
    // 是否自动检测设备（如果为 false，则使用自定义配置）
    bool auto_detect = true;

    // 自动检测时使用的设备标识符
    HIDDeviceIdentifier input_identifier{};

    // 自定义配置（当 auto_detect = false 时使用）
    struct CustomConfig {
        u16 vendor_id{0x046d};      // 默认罗技
        u16 product_id{0xc52b};     // 默认罗技鼠标
        std::string manufacturer{"HIDBox"};
        std::string product{"Virtual HID Device"};
        std::string serial;
        std::vector<u8> report_descriptor;  // 自定义报告描述符
    } custom;

    // Gadget 配置
    std::string gadget_name = "hidbox";
    u32 hid_number = 0;  // /dev/hidgN 的编号
};

/**
 * @brief HID 设备管理器
 * 负责管理 HID 设备的配置、透传和模拟
 */
class HIDDeviceManager {
public:
    HIDDeviceManager();
    ~HIDDeviceManager();

    /**
     * @brief 配置并初始化 HID 设备
     * @param config 设备配置
     */
    void Configure(const HIDDeviceConfig& config);

    /**
     * @brief 启动透传模式
     * 从物理设备读取输入并转发到虚拟设备
     */
    void StartPassthrough();

    /**
     * @brief 停止透传模式
     */
    void StopPassthrough();

    /**
     * @brief 写入数据到虚拟 HID 设备
     * @param data 数据指针
     * @param size 数据大小
     * @return 写入的字节数
     */
    ssize_t WriteToOutput(const void* data, size_t size);

    /**
     * @brief 设置输入数据回调
     * @param callback 回调函数
     */
    void SetInputCallback(std::function<void(u8* data, u32 length)> callback) {
        input_callback = std::move(callback);
    }

    /**
     * @brief 获取输入设备描述符
     * @return HIDGadgetDescriptor 指针，如果未配置则返回 nullptr
     */
    const HIDGadgetDescriptor* GetInputDescriptor() const;

private:
    std::unique_ptr<UsbGadget> gadget;
    std::unique_ptr<InputHIDDevice> input_device;
    std::unique_ptr<OutputHIDDevice> output_device;
    std::function<void(u8* data, u32 length)> input_callback;
    HIDDeviceConfig current_config;
    bool is_passthrough_active = false;

    void ConfigureWithAutoDetect(const HIDDeviceConfig& config);
    void ConfigureWithCustom(const HIDDeviceConfig& config);
    void OnInputData(u8* data, u32 length);
};

}  // namespace hidbox
